Can Hazel be set to make hard links of files?

Get help. Get answers. Let others lend you a hand.

Moderator: Mr_Noodle

Can Hazel be set to make hard links of files? Fri Mar 12, 2010 6:00 pm • by tiny-e
This may be a feature request in disguise...

Is there a way to get hazel to hard link a file instead of copying or moving it? This would serve to prevent hazel from borking torrent seeding when it does the rest of its magic.
tiny-e
 
Posts: 22
Joined: Fri Mar 12, 2010 5:51 pm

You'd have to use a shell script for that with the 'ln' command. I probably won't add it as a standard action since it's fairly uncommon plus not very well understood by most users.

How exactly is Hazel borking your torrents?
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Thanks for the reply.

It's messing them up by moving them (like it's supposed to) to a different folder for consideration by another piece of software (EpidodeLinker script). Only problem is, they are not done seeding before they get moved, so the torrent client can't find the files any more.

Seeing as you can't hard link folders (I think), I would need to figure out a way to tell it via applescript or shell script to "mirror" the folder (if the torrent contains one) and its contents via hard linking on an individual basis.

Not really sure how to do this, how to pass the file or folder names/paths from hazel to the script.
tiny-e
 
Posts: 22
Joined: Fri Mar 12, 2010 5:51 pm

tiny-e wrote:Seeing as you can't hard link folders (I think), I would need to figure out a way to tell it via applescript or shell script to "mirror" the folder (if the torrent contains one) and its contents via hard linking on an individual basis.


You're correct in that you can't hard link folders, but I can't really think of a good reason why you would need to use a hard link at all. It's a lot cleaner to just use a symbolic link, using the ln command with the -s flag.

tiny-e wrote:Not really sure how to do this, how to pass the file or folder names/paths from hazel to the script.


The file is the first argument sent to the script, so, in C, that would be argv[1] (since argv[0] is the filename of the program being invoked). In shell scripting, you can use $1 to get that first argument. In the code below, you have to surround $1 in quotes in order to get it to correctly handle files or folders with spaces in their name.

You have to set the rule to match "Any File," which will match both files and directories and then set the action to "Run shell script" with embedded script chosen as your source. The default shell (/bin/sh) should be fine. Then, paste the following code into the large text area:

Code: Select all
ln -s "$1" /absolute/path/to/directory/where/your/other/script/can/run/


Why did you want to use hard links instead of symbolic links? Will your custom script not correctly follow symlinks?
holigen
 
Posts: 18
Joined: Tue Mar 16, 2010 2:43 am

I'm kinda following an example (the other script that renames the files). Assuming the reason would be that hard linking allows the same file to
be in two different places with 2 different names without breaking the torrents seeding.
tiny-e
 
Posts: 22
Joined: Fri Mar 12, 2010 5:51 pm

tiny-e wrote:I'm kinda following an example (the other script that renames the files).


Which other script is that? I searched but couldn't find anything that looked similar to the problem you're having.

tiny-e wrote:Assuming the reason would be that hard linking allows the same file to be in two different places with 2 different names without breaking the torrents seeding.


Alright, well, it seems like symbolically linking the files would work in this case too.

The difference between symbolic linking and hard linking is that a symbolic link points to just the filename itself on the computer (what you see in Finder) whereas a hard link is basically another file name that points to the same block of memory as the source of the link.

As long as you're not going to be moving the file you're linking against, the symbolic link will still point to the correct file. Try creating and using a symbolic link to access the files or folders from another folder.
holigen
 
Posts: 18
Joined: Tue Mar 16, 2010 2:43 am

The script is called by a custom application called Episode Linker that scans a folder or folders for movie files that match known TV series episode naming convention, cleans up the names (removes things like release group names, etc) and copies, moves, or hard-links them to the TV shows folder in Plex.app (awesome media center forked from XMBC for Intel Macs http://www.plexapp.com). The guts of the script are protected if I remember correctly.

I believe symbolic links break seeding in Transmission... Copying would be easy, but would double, or more, the disk space burned while the torrent is seeding...

Couldn't I use your example from before and just make the 'ln' part a hard link?

Thanks for helping out!

As a note: If Mr. Noodle is still watching this topic, having provision for similar functionality OOTB in Hazel would probably endear your software to the gazillion or so people that actively use Plex.app (although a ton of them are from overseas so you may need language support (not sure if Hazel has it))
tiny-e
 
Posts: 22
Joined: Fri Mar 12, 2010 5:51 pm

If Episode Linker copies or hard links the file before it starts to rename that copy or hard link, then you should be fine just running it on your seeding folder itself. However, if it tries to rename the original file that Transmission is seeding, then Transmission will probably try to download the file again with the original filename, thinking that it has been deleted.

tiny-e wrote:The guts of the script are protected if I remember correctly.


They definitely are -- I just checked and the AppleScripts that are used were saved as run-only.

tiny-e wrote:I believe symbolic links break seeding in Transmission.


I don't think that symbolic links do it, but renaming the file definitely breaks seeding in Transmission. It changes the hash (unique identifier) that is used to verify that you're actually sending the correct file over the network.

I'm not sure you can get away with renaming the file while Transmission is seeding it without making a hard link of the file and then naming that something else.

tiny-e wrote:Couldn't I use your example from before and just make the 'ln' part a hard link?


You could, but it wouldn't work for folders. The script would have to go into each folder and then hard link the files individually, like you suggested earlier. I'll work on a script that would do this, though, and post back here probably tomorrow.
holigen
 
Posts: 18
Joined: Tue Mar 16, 2010 2:43 am

Sorry about the delay in getting to you. Just got back in town from a trip and am only now getting back on top of things.

Actually, you can do hard links to directories in OS X as it is used by Time Machine. You can get more details here: http://arstechnica.com/apple/reviews/20 ... 0-5.ars/14

That said, I'm not sure how to actually do it yourself but it's something you can search around for.

You could try and get a hold of the author of Episode Linker. It seems that if it is creating links, that it should be able to operate on the file still in the torrent directory without disturbing it.

Also, you can copy the file as suggested and then remove the original version being used to seed some time later. I don't know how you determine when you are done seeding so you'll have to figure out some mechanism for that. You'd have to do that anyways since even if you managed to do hard links, you'd want to delete the old hard link to the file in the torrent directory eventually.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

If you really want to try hard linking directories, you actually can do that in Mac OS X Leopard and later. Mr_Noodle is correct -- Time Machine uses hard linked directories to simplify a lot of the backup work it has to do. The caveat is that it's not easy. You have to write and compile your own hard linking utility to do that, since the built-in ln command will check to see if you're trying to hard link a directory and then tell you that you can't. I'll post up the code for that utility at the end of this post, if you want to go down that road (which I don't suggest).

Right now, I'm just going to show you a script I wrote that attempts to mirror a directory structure using hard links.

You'll want to make sure this rule only works on folders and then those that Hazel hasn't matched before, so you would set the rule to match a folder with the date last matched being blank. The action is an embedded script, like before, except with the "shell" being /usr/bin/python and the following as its contents:

Code: Select all
import os;
import sys;
import subprocess;

# replace the path in between the quotes with the folder where you want folders to end up
destinationPath = "/absolute/path/to/destination/";

sourcePathLength = len(sys.argv[1]);

for current, directories, files in os.walk(sys.argv[1]):
    currentDestination = os.path.join(destinationPath, current[sourcePathLength:]);
   
    if not os.path.exists(currentDestination):
        os.mkdir(currentDestination);
   
    for item in files:
        subprocess.Popen(["ln", os.path.join(current, item), os.path.join(currentDestination, item)], stdout = subprocess.PIPE);


For files, another rule with a similar structure to the one given above (for symbolic links, so, in the case, omit the -s flag) will work.

If you have the Apple Developer Tools installed and you feel a bit adventurous, then you can write some C code that will let you hard link folders directly. Keep in mind, though, that this is a bit dangerous and I haven't tried it. Even though Apple tried to make this safe, I'm not sure if it really is. The danger is that you could create an infinite loop inside the file structure with a folder containing a hard link to itself, which will then contain that same hard link. The same thing can happen with symbolic links, but symbolic links are functionally different from the file itself. That is not the case with hard links and the operating system cannot tell them apart. I believe that Apple does try to keep you from shooting yourself in your foot, but again, use caution when using this method.

You'll need to, first, create the command that will hard link directories. You'll have to compile this command yourself. Open up a text editor (in plain text mode, in the case of TextEdit) and type in the following code:

Code: Select all
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
   if (argc != 3)
      return 1;
   int ret = link(argv[1], argv[2]);
   if (ret != 0)
      perror("link");
   return ret;
}


Save this file as hlink.c to a convenient location, like your Desktop.

Next, you’ll have to compile that code. Open up Terminal.app (in /Applications/Utilities/) and type in the following (if you saved it to your Desktop, if not, then change your directory to the location you saved it):

Code: Select all
cd ~/Desktop
gcc -o hlink hlink.c -Wall
chmod 755 hlink


This will give you another file on your Desktop called hlink. This command can be executed (because we changed its permissions) now. I would suggest placing the hlink file in a safe place (like /usr/bin/, since it’s probably already on your path) so you can access the command from anywhere on your computer.

Next, you can just invoke it like the ln command as seen in the previous symbolic link example referenced earlier.

If you want an exhaustive review of hard linking directories, Exploring Leopard with DTrace by Greg Miller is an excellent place to start (all of the credit for the above C code goes to Greg), if you scroll all the way to the last few paragraphs of the article.
holigen
 
Posts: 18
Joined: Tue Mar 16, 2010 2:43 am

Sorry for the late reply -- I must have missed an email somewhere.

Thanks again for all the help. I've been able to use some of what's posted here to get hard links going for certain files --and that's a step in the right direction!

I will look into the mirroring part as I progress in my approach to this problem.

Thanks! :D
tiny-e
 
Posts: 22
Joined: Fri Mar 12, 2010 5:51 pm


Return to Support